﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FreightSoft.Models;
using FreightSoft.Classes;

namespace FreightSoft.Controllers
{
    public class TrackingController : Controller
    {
        private Entities db = new Entities();
        OzekiSMS sms = new OzekiSMS();
        
        //
        // GET: /Tracking/

        public ActionResult Index(string message_)
        {
            //sms.SendSMS("0094715205458","search"); 
            //message_ = calculateTime("HKHKG", "ZAZBA").ToString();
            ViewBag.Message = message_;
            return View();
        }

        public ActionResult Detail(string OrdNo, string Command)
        {
            string OrderNo = "";
          
            List<ROUTECOORDINATE> roots = new List<ROUTECOORDINATE>();
            List<ROUTECOORDINATE> coordinate1 = new List<ROUTECOORDINATE>();
            List<ROUTECOORDINATE> coordinate2 = new List<ROUTECOORDINATE>();
            List<ROUTECOORDINATE> coordinate3 = new List<ROUTECOORDINATE>();
            List<ROUTECOORDINATE> coordinate4 = new List<ROUTECOORDINATE>();

            List<List<double>> coords = new List<List<double>>();
            List<List<double>> weatherCoords = new List<List<double>>();
            List<WeatherDetails> wheather_ = new List<WeatherDetails>();

            var preDesPort_ = "";
            var originPort = "";
            var desPort   = "";
            var nowPort = "";

            decimal nowPortLat;
            decimal nowPortLon;
           
            DateTime wantedDelDate = new DateTime();
            DateTime plannedShipmentDate = new DateTime();
            DateTime estimatedDelDate = new DateTime();

            SHIPMENT shipment_ = new SHIPMENT();
            string notInShipment = "";

            try
            {
                OrderNo = OrdNo.Substring(5, (OrdNo.Length - 7));                          
                originPort = db.CUSTOMER_ORDER.Find(int.Parse(OrderNo)).SOURCE;
                desPort = db.CUSTOMER_ORDER.Find(int.Parse(OrderNo)).DESTINATION;
            }
            catch (Exception)
            {
                return RedirectToAction(actionName: "Index", routeValues: new { message_ = "Wrong tracking number. Please enter correct number" });
            }

            wantedDelDate = db.CUSTOMER_ORDER.Find(int.Parse(OrderNo)).WANTED_DELIVERY_DATE;

            try
            {
                decimal o = decimal.Parse(OrderNo);
                var shipment = (from s in db.SHIPMENTLINEs where s.ORDERID == o select s).ToList().First();
                shipment_ = db.SHIPMENTs.Find(shipment.SHIPMENTID);
                plannedShipmentDate = shipment_.PLANNED_START_DATE.GetValueOrDefault();
                //plannedShipmentDate = DateTime.Now;
                int totHours_ = calculateTime(shipment_.ORIGINPORT, shipment_.DESTINATIONPORT);
                //int totHours_ = calculateTime(originPort, desPort);
                //int totHours_ = calculateTime("HKHKG", "ZAZBA");
                estimatedDelDate = plannedShipmentDate.AddDays(totHours_ / 24);
                //plannedShipDate = DateTime.Now.AddDays(totHours_ / 24);
            }
            catch (Exception e)
            {
                notInShipment = "Order is not shipped yet.";
            }

            //current port
            nowPort = originPort;
            if (notInShipment == "")
            {
                //ship port
                SHIPMENTSCHEDULE schedule_ = (from i in db.SHIPMENTSCHEDULEs where i.SCHEDULEID == shipment_.SCHEDULEID select i).ToList().FirstOrDefault();
                if (schedule_ != null)
                {
                    if (schedule_.CURRENT_PORT != null)
                    {
                        nowPort = schedule_.CURRENT_PORT;
                    }                    
                }
            }

            //Root coordinate calculation
            ROUTECOORDINATE c = (from i in db.ROUTECOORDINATES where i.ORIGIN_PORT_ID == nowPort && i.COORDINATE_ORDER == 0 select i).ToList().FirstOrDefault();
            nowPortLat = c.LAT.GetValueOrDefault();
            nowPortLon = c.LON.GetValueOrDefault();
            
            coordinate1 = (from r in db.ROUTECOORDINATES where r.ORIGIN_PORT_ID == originPort orderby r.COORDINATE_ORDER select r).ToList();

            preDesPort_ = (from i in coordinate1 select i.DEST_PORT_ID).ToList().FirstOrDefault();
            if (preDesPort_ != desPort && preDesPort_ != null)
            {
                coordinate2 = (from r in db.ROUTECOORDINATES where r.ORIGIN_PORT_ID == preDesPort_ orderby r.COORDINATE_ORDER select r).ToList();
            }

            preDesPort_ = (from i in coordinate2 select i.DEST_PORT_ID).ToList().FirstOrDefault();
            if (preDesPort_ != desPort && preDesPort_ != null)
            {
                coordinate3 = (from r in db.ROUTECOORDINATES where r.ORIGIN_PORT_ID == preDesPort_ orderby r.COORDINATE_ORDER select r).ToList();
            }

            preDesPort_ = (from i in coordinate3 select i.DEST_PORT_ID).ToList().FirstOrDefault();
            if (preDesPort_ != desPort && preDesPort_ != null)
            {
                coordinate4 = (from r in db.ROUTECOORDINATES where r.ORIGIN_PORT_ID == preDesPort_ orderby r.COORDINATE_ORDER select r).ToList();
            }

            foreach (ROUTECOORDINATE item in coordinate1)
            {
                roots.Add(item);               
            }

            foreach (ROUTECOORDINATE item in coordinate2)
            {
                roots.Add(item);
            }

            foreach (ROUTECOORDINATE item in coordinate3)
            {
                roots.Add(item);
            }

            foreach (ROUTECOORDINATE item in coordinate4)
            {
                roots.Add(item);
            }

            //nowPortLat = Convert.ToDecimal(1.0789109);
            //nowPortLon = Convert.ToDecimal(103.9882063);
            int counter_ = 0;
            int pass = 0;
            foreach (var item in roots)
            {              
                coords.Add(new List<double>() { (double)item.LAT, (double)item.LON });
                if ((double)item.LAT == (double)nowPortLat && (double)item.LON == (double)nowPortLon)
                {
                    pass = 1;
                }
                if (pass == 1)
                {
                    if (counter_ % 2 == 0)
                    {
                        weatherCoords.Add(new List<double>() { (double)item.LAT, (double)item.LON });
                    }
                    counter_++;
                }               
            }
            
            wheather_ = getWheather(weatherCoords);

            ViewBag.OrderNo = OrderNo;
            ViewBag.WantedDelDate = wantedDelDate;
            ViewBag.ShipmentDate = notInShipment != "" ? notInShipment: plannedShipmentDate.ToString();
            ViewBag.EstimatedDelDate = notInShipment != "" ? notInShipment : estimatedDelDate.ToString();           
            ViewBag.ShippingTime = calculateTime(nowPort,desPort);
            ViewBag.Weather = notInShipment == "" ? wheather_:null;
            ViewBag.Prediction = notInShipment == "" ? predict(wheather_):null;
            ViewBag.Coordinates = coords;
            ViewBag.ShipLat = nowPortLat; // 22.3189226;
            ViewBag.ShipLon = nowPortLon; // 113.817885;
            return View();
        }

        public string predict(List<WeatherDetails> wheather)
        {
            var d = (from i in wheather where int.Parse(i.WeatherNumber) == 781 || int.Parse(i.WeatherNumber) == 900 select i.WeatherDay).ToList().FirstOrDefault();
            if (d != null)
            {
                return ("Delayed, Tornado on " + d);
            }

            var d1 = (from i in wheather where int.Parse(i.WeatherNumber) > 200 && int.Parse(i.WeatherNumber) < 240 select i.WeatherDay).ToList().FirstOrDefault();
            if (d1 != null)
            {
                return ("Delayed, Thunderstorm on " + d1);
            }

            var d2 = (from i in wheather where int.Parse(i.WeatherNumber) == 960 || int.Parse(i.WeatherNumber) == 961 select i.WeatherDay).ToList().FirstOrDefault();
            if (d2 != null)
            {
                return ("Delayed, Storm on " + d2);
            }

            var d3 = (from i in wheather where int.Parse(i.WeatherNumber) > 499 && int.Parse(i.WeatherNumber) < 550 select i.WeatherDay).ToList().FirstOrDefault();
            if (d3 != null)
            {
                return ("May be delayed, Rain on " + d3);
            }

            var d4 = (from i in wheather where int.Parse(i.WeatherNumber) > 299 && int.Parse(i.WeatherNumber) < 350 select i.WeatherDay).ToList().FirstOrDefault();
            if (d4 != null)
            {
                return ("On Time Delivery, Drizzle on " + d4);
            }

            var d5 = (from i in wheather where int.Parse(i.WeatherNumber) > 799 && int.Parse(i.WeatherNumber) < 806 select i.WeatherDay).ToList().FirstOrDefault();
            if (d5 != null)
            {
                return "On Time Delivery";
            }

            return "On Time Delivery";
                       
        }

        public int calculateTime(string originPort, string destPort)
        {    
            var routecoordinate_ = (from r in db.ROUTECOORDINATES where r.ORIGIN_PORT_ID == originPort && r.COORDINATE_ORDER == 0 select r).ToList().First();
            int time_ = (int)routecoordinate_.DURATION.GetValueOrDefault();
            if (routecoordinate_.DEST_PORT_ID != destPort)
            {
                time_ += calculateTime(routecoordinate_.DEST_PORT_ID, destPort);
            }            
            return time_;            
        }

        private List<WeatherDetails> getWheather(List<List<double>> coords)
        {
            List<WeatherDetails> wheather_ = new List<WeatherDetails>();
            List<WeatherDetails> locationWheather_ = new List<WeatherDetails>();
            Weather w = new Weather();
            int i_ = 1;

            foreach (List<double> c_ in coords)
            {
                locationWheather_ = w.GetWeather(c_[0], c_[1],i_);
                wheather_.Add(locationWheather_.LastOrDefault());
                i_++;
            }
            return wheather_;
        }
    }
}
